package com.xp.flow.component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据转换组件
 * 支持字段映射和转换脚本，实现复杂的数据结构转换
 * 
 * @author AI Assistant
 * @since 1.0.0
 */
@Slf4j
@LiteflowComponent("DATA_TRANSFORM")
public class DataTransformComponent extends BaseFlowComponent {

    @Autowired
    private ObjectMapper objectMapper;
    
    private final ExpressionParser expressionParser = new SpelExpressionParser();
    private final ScriptEngineManager scriptEngineManager = new ScriptEngineManager();

    @Override
    public void process() {
        // 获取配置
        String description = getConfigValue("description", "数据转换");
        
        logExecution("开始执行数据转换: %s", description);
        
        // 获取输入数据
        Map<String, Object> inputData = getInputData();
        
        try {
            // 执行数据转换
            Map<String, Object> transformedData = executeTransformation(inputData);
            
            // 设置输出数据
            setOutputData(transformedData);
            
            logExecution("数据转换完成，输出字段数: %d", transformedData.size());
            
        } catch (Exception e) {
            logError("数据转换执行失败", e);
            
            // 创建错误输出
            Map<String, Object> errorData = new HashMap<>(inputData);
            errorData.put("error", true);
            errorData.put("errorMessage", "数据转换失败: " + e.getMessage());
            errorData.put("success", false);
            
            setOutputData(errorData);
        }
    }
    
    /**
     * 执行数据转换
     * 
     * @param inputData 输入数据
     * @return 转换后的数据
     * @throws Exception 转换异常
     */
    private Map<String, Object> executeTransformation(Map<String, Object> inputData) throws Exception {
        Map<String, Object> result = new HashMap<>();
        
        // 1. 执行字段映射
        Map<String, Object> mappedData = executeFieldMapping(inputData);
        result.putAll(mappedData);
        
        // 2. 执行转换脚本
        Map<String, Object> scriptResult = executeTransformScript(result);
        result.putAll(scriptResult);
        
        // 3. 添加元数据
        result.put("transformSuccess", true);
        result.put("originalDataSize", inputData.size());
        result.put("transformedDataSize", result.size());
        
        return result;
    }
    
    /**
     * 执行字段映射
     * 
     * @param inputData 输入数据
     * @return 映射后的数据
     */
    private Map<String, Object> executeFieldMapping(Map<String, Object> inputData) {
        Map<String, Object> result = new HashMap<>();
        
        // 获取字段映射配置
        Object mappingConfig = getConfigValue("fieldMapping", null);
        
        if (mappingConfig == null) {
            // 如果没有配置映射，直接返回输入数据
            return new HashMap<>(inputData);
        }
        
        try {
            Map<String, Object> mappings;
            if (mappingConfig instanceof Map) {
                mappings = (Map<String, Object>) mappingConfig;
            } else {
                // 尝试解析为JSON
                mappings = objectMapper.readValue(mappingConfig.toString(), Map.class);
            }
            
            // 执行字段映射
            for (Map.Entry<String, Object> mapping : mappings.entrySet()) {
                String targetField = mapping.getKey();
                Object sourceConfig = mapping.getValue();
                
                Object value = extractFieldValue(inputData, sourceConfig);
                if (value != null) {
                    result.put(targetField, value);
                }
            }
            
            logExecution("字段映射完成，映射了 %d 个字段", result.size());
            
        } catch (Exception e) {
            logError("字段映射执行失败", e);
            // 映射失败时返回原始数据
            return new HashMap<>(inputData);
        }
        
        return result;
    }
    
    /**
     * 提取字段值
     * 
     * @param data 数据源
     * @param sourceConfig 源字段配置
     * @return 提取的值
     */
    private Object extractFieldValue(Map<String, Object> data, Object sourceConfig) {
        if (sourceConfig instanceof String) {
            String sourceField = (String) sourceConfig;
            
            // 支持嵌套字段访问，如 "user.name"
            if (sourceField.contains(".")) {
                return getNestedValue(data, sourceField);
            } else {
                return data.get(sourceField);
            }
            
        } else if (sourceConfig instanceof Map) {
            Map<String, Object> config = (Map<String, Object>) sourceConfig;
            
            // 支持表达式映射
            String expression = (String) config.get("expression");
            if (expression != null) {
                return evaluateExpression(expression, data);
            }
            
            // 支持默认值
            String sourceField = (String) config.get("source");
            Object defaultValue = config.get("default");
            
            Object value = sourceField != null ? data.get(sourceField) : null;
            return value != null ? value : defaultValue;
        }
        
        return null;
    }
    
    /**
     * 获取嵌套字段值
     * 
     * @param data 数据源
     * @param fieldPath 字段路径，如 "user.name"
     * @return 字段值
     */
    private Object getNestedValue(Map<String, Object> data, String fieldPath) {
        String[] parts = fieldPath.split("\\.");
        Object current = data;
        
        for (String part : parts) {
            if (current instanceof Map) {
                current = ((Map<String, Object>) current).get(part);
            } else {
                return null;
            }
        }
        
        return current;
    }
    
    /**
     * 评估表达式
     * 
     * @param expression 表达式
     * @param data 数据上下文
     * @return 表达式结果
     */
    private Object evaluateExpression(String expression, Map<String, Object> data) {
        try {
            StandardEvaluationContext context = new StandardEvaluationContext();
            
            // 设置数据上下文
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                context.setVariable(entry.getKey(), entry.getValue());
            }
            context.setVariable("input", data);
            
            Expression expr = expressionParser.parseExpression(expression);
            return expr.getValue(context);
            
        } catch (Exception e) {
            logError("表达式评估失败: " + expression, e);
            return null;
        }
    }
    
    /**
     * 执行转换脚本
     * 
     * @param data 输入数据
     * @return 脚本执行结果
     */
    private Map<String, Object> executeTransformScript(Map<String, Object> data) {
        String script = getConfigValue("transformScript", null);
        
        if (script == null || script.trim().isEmpty()) {
            return new HashMap<>();
        }
        
        try {
            ScriptEngine engine = scriptEngineManager.getEngineByName("javascript");
            if (engine == null) {
                engine = scriptEngineManager.getEngineByName("nashorn");
            }
            
            if (engine == null) {
                logError("JavaScript引擎不可用，跳过脚本执行", null);
                return new HashMap<>();
            }
            
            // 设置脚本上下文
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                engine.put(entry.getKey(), entry.getValue());
            }
            engine.put("input", data);
            engine.put("output", new HashMap<String, Object>());
            
            // 执行脚本
            Object result = engine.eval(script);
            
            // 获取输出结果
            Object outputObj = engine.get("output");
            if (outputObj instanceof Map) {
                return (Map<String, Object>) outputObj;
            } else if (result instanceof Map) {
                return (Map<String, Object>) result;
            }
            
            logExecution("转换脚本执行完成");
            
        } catch (Exception e) {
            logError("转换脚本执行失败", e);
        }
        
        return new HashMap<>();
    }
}